#ifndef _ARCH_CACHE_H
#define _ARCH_CACHE_H

#include <arch/arm.h>
#include <compiler.h>

#define ICACHE_SIZE                 0x4000
#define ICACHE_LINE_SIZE            32
#define ICACHE_WAYS                 64
#define ICACHE_SETS (ICACHE_SIZE/(ICACHE_LINE_SIZE*ICACHE_WAYS))

#define DCACHE_SIZE                 0x4000
#define DCACHE_LINE_SIZE            32
#define DCACHE_WAYS                 64
#define DCACHE_SETS (DCACHE_SIZE/(DCACHE_LINE_SIZE*DCACHE_WAYS))

static inline void icache_enable(void)
{
	set_cr(get_cr() | CR_I);
}

static inline void icache_disable(void)
{
	set_cr(get_cr() & ~CR_I);
}

static inline void icache_invalidate_all(void)
{
	asm("mcr p15, 0, %0, c7, c5, 0"
		:
		: "r" (0));
}

static int __maybe_unused icache_is_enabled(void)
{
	return get_cr() & CR_I;
}

static inline void dcache_enable(void)
{
	set_cr(get_cr() | CR_C);
}

static inline void dcache_disable(void)
{
	set_cr(get_cr() & ~CR_C);
}

static inline void dcache_invalidate_all(void)
{
	asm("mcr p15, 0, %0, c7, c6, 0"
		:
		: "r" (0));
}

static inline void dcache_flush_all(void)
{
	int i, j;

	for (i = 0; i < DCACHE_SETS; i++) 
		for (j = 0; j < DCACHE_WAYS; j++) 
			asm("mcr p15, 0, %0, c7, c10, 2"
				:
				: "r" ((j << 26) | (i << 5)));			
}

#endif /* _ARCH_CACHE_H */

